package com.hengyu.auth.controller;

import com.hengyu.auth.constants.YAuthConstants;
import com.hengyu.auth.entity.TokenInfoEntity;
import com.hengyu.auth.entity.UserInfoEntity;
import com.hengyu.auth.jpa.TokenInfoDAO;
import com.hengyu.auth.jpa.UserInfoDAO;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.util.Date;

/**
 * 获取Token控制器
 * 根据appId以及appSecret动态生成jwt,Token值并且存储到数据库
 * ========================
 * Created with IntelliJ IDEA.
 * User：恒宇少年
 * Date：2017/3/27
 * Time：23:03
 * 码云：http://git.oschina.net/jnyqy
 * ========================
 */
@RestController
public final class TokenController implements Serializable{

    @Autowired
    private UserInfoDAO userInfoJpa;

    @Autowired
    private TokenInfoDAO tokenInfoDAO;

    @RequestMapping(value = "/token", method = {RequestMethod.POST,RequestMethod.GET})
    public Token login
            (
                    @RequestParam String appId,
                    @RequestParam String appSecret
            )
            throws Exception
    {
        Token token = new Token();
        //appId is null
        if(appId == null || appId.trim() == "")
        {
            token.setFlag(false);
            token.setMsg("appId is not found!");
        }
        //appSecret is null
        else if(appSecret == null || appSecret.trim() == "")
        {
            token.setFlag(false);
            token.setMsg("appSecret is not found!");
        }
        else
        {
            //根据appId查询用户实体
            UserInfoEntity userDbInfo = userInfoJpa.findOne(new Specification<UserInfoEntity>() {
                @Override
                public Predicate toPredicate(Root<UserInfoEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                    criteriaQuery.where(criteriaBuilder.equal(root.get("appId"), appId));
                    return null;
                }
            });
            //如果不存在
            if (userDbInfo == null)
            {
                token.setFlag(false);
                token.setMsg("appId : " + appId + ", is not found!");
            }
            //验证appSecret是否存在
            else if (!new String(userDbInfo.getAppSecret()).replace("+", " ").equals(appSecret))
            {
                token.setFlag(false);
                token.setMsg("appSecret is not effective!");
            }
            else
            {
                //获取当前时间
                Date now = new Date(System.currentTimeMillis());
                //过期时间
                Date expiration = new Date(now.getTime() + 7200000);
                //生成jwt,Token
                String tokenStr = Jwts
                        .builder()
                        .setSubject(appId)
                        .claim(YAuthConstants.Y_AUTH_ROLES, userDbInfo.getRoles())
                        .setIssuedAt(now)
                        .setIssuer("Online YAuth Builder")
                        .setExpiration(expiration)
                        .signWith(SignatureAlgorithm.HS256, YAuthConstants.Y_AUTH)
                        .compact();
                //检测数据库是否存在该appId的token值
                TokenInfoEntity tokenDBEntity = tokenInfoDAO.findOne(new Specification<TokenInfoEntity>() {
                    @Override
                    public Predicate toPredicate(Root<TokenInfoEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                        criteriaQuery.where(criteriaBuilder.equal(root.get("appId"), appId));
                        return null;
                    }
                });
                //如果数据库中不存在该appid的token值
                if(tokenDBEntity == null)
                {
                    //将token保持到数据库
                    tokenDBEntity = new TokenInfoEntity();
                    tokenDBEntity.setAppId(userDbInfo.getAppId());
                    tokenDBEntity.setBuildTime(String.valueOf(now.getTime()));
                    tokenDBEntity.setToken(tokenStr.getBytes());
                    tokenInfoDAO.save(tokenDBEntity);
                }
                //如果数据库中存在该appid的token值，更新token
                else
                {
                    tokenDBEntity.setToken(tokenStr.getBytes());
                    tokenInfoDAO.save(tokenDBEntity);
                }
                //设置返回token
                token.setToken(tokenStr);
            }
        }
        return token;
    }

    class Token implements Serializable{
        private boolean flag = true;
        private String msg = "";
        private String token ="";

        public boolean isFlag() {
            return flag;
        }

        public void setFlag(boolean flag) {
            this.flag = flag;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }
    }
}
